﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace robot
{
    /**
     * Gestion de la liste des salles
     */
    class Terrain
    {

        /**
         * On enregistre le nom des entrées et sorties possibles (ex NORD, EST)
         */
        private static HashSet<String> nomsSorties = new HashSet<string>();
        /**
         * On enregistre également la correspondance entre 2 entrées/sorties pour rester concordant :
         * typiquement la sortie NORD d'une salle correspond à la sortie SUD de la salle voisine
         */
        private static Dictionary<string, string> correspNoms = new Dictionary<string, string>();


        private List<Salle> terrain;

        /**
         * onstruction manuel du terrain
         */
        public Terrain()
        {
            terrain = new List<Salle>();
        }

        /**
         * Ajoute une salle sur le terrain, sans voisin
         */ 
        public void addSalle()
        {
            terrain.Add(new Salle(new Random().Next(10)));
        }

        /**
         * Crée une porte entre deux salles
         */
        public void addVoisin(string direction, int indiceSalle, int indiceSalleVoisine)
        {
            terrain[indiceSalle].AjoutVoisin(terrain[indiceSalleVoisine], direction);
            terrain[indiceSalleVoisine].AjoutVoisin(terrain[indiceSalle], correspNoms[direction]);
        }

        public static void AjoutSorties(String nom)
        {
            nom = nom.ToLower();
            if( ! nomsSorties.Contains(nom))
                nomsSorties.Add(nom);
        }

        public static bool SupprimerSorties(String nom)
        {
            return nomsSorties.Remove(nom);
        }

        /**
         * fait la correspondance entre 2 noms de sorties (ex : nord et sud)
         */
        public static void AjoutCorrespondance(String sortie, String entree)
        {
            sortie = sortie.ToLower();
            entree = entree.ToLower();
            AjoutSorties(sortie);
            AjoutSorties(entree);

            correspNoms.Remove(sortie);
            correspNoms.Remove(entree);

            correspNoms.Add(sortie, entree);
            correspNoms.Add(entree, sortie);
        }

       
        public static Terrain TerrainAleatoire(int largeur, int longueur)
        {
            Terrain terrain = new Terrain();
            terrain.CreationSalles(largeur, longueur);

            return terrain;
        }


        /**
         * Retourne la premiere salle
         */
        public Salle Entrer()
        {
            return terrain[0];
        }

        /**
         * Retourne la salle qui se trouve a a position pos
         */
        public Salle this[int pos]
        {
            get
            {
                return terrain[pos];
            }
        }

        /**
         * Initialisation des salles
         */
        public void CreationSalles(int largeur, int longueur)
        {
            if (largeur < 2)
                largeur = 2;
            if (longueur < 2)
                longueur = 2;

            terrain.Clear();

            for (int i = 0; i < largeur * longueur; i++)
            {
                terrain.Add(new Salle(new Random().Next(10)));
            }
            VoisinsAleatoire(largeur, longueur);
        }

        /**
         * Création d'une grille aléatoire de largeur et de longueur passer en parametre
         */
        private void VoisinsAleatoire(int largeur, int longueur)
        {
            
            Terrain.AjoutCorrespondance("nord", "sud");
            Terrain.AjoutCorrespondance("est", "ouest");

            Random rand = new Random();
            int i;
            for (int x = 0; x< largeur; x++)
                for(int y = 0; y<longueur; y++)
                {
                    i = x + y *largeur;
                    // on est au bord droit
                    if (x == 0)
                    {
                        addVoisin("est", i, x + 1 + y * largeur);
                        if(y == 0 ){ 
                            if(rand.Next(1) > 0)
                                addVoisin("sud", i, x + (y + 1) * largeur);
                        }
                        else  if(y == longueur - 1 ){
                            if (rand.Next(1) > 0)
                                addVoisin("nord", i, x + (y - 1) * largeur);
                        }
                    }

                    else if (x == largeur)
                    {
                        addVoisin("ouest", i, x - 1 + y * largeur);
                        if (y == 0)
                        {
                            if (rand.Next(1) > 0)
                                addVoisin("sud", i, x + (y + 1) * largeur);
                        }
                        else  if(y == longueur - 1 ){
                            if (rand.Next(1) > 0)
                                addVoisin("nord", i, x + (y - 1) * largeur);
                        }
                    }
                    else if (y == 0)
                        addVoisin("sud", i, x + (y + 1) * largeur);
                    else if (y == longueur - 1)
                        addVoisin("nord", i, x + (y - 1) * largeur);

                    else // on n'es pas sur un bord
                    {
                        if(rand.Next(4) == 0)
                            terrain[i].AjoutVoisin(terrain[x + (y + 1) * largeur], "sud");
                        if (rand.Next(4) == 0)
                            terrain[i].AjoutVoisin(terrain[x + (y - 1) * largeur], "nord");
                        if (rand.Next(4) == 0)
                            terrain[i].AjoutVoisin(terrain[x - 1 + y * largeur], "ouest");
                        if (rand.Next(4) == 0)
                            terrain[i].AjoutVoisin(terrain[x + 1 + y * largeur], "est");
                    }   
              }
        }



        /**
         * Vérifie que la string appartient aux directions possible
         */
        static public bool DirectionValide(String direction)
        {
            return nomsSorties.Contains(direction);
        }

        /**
         * Retourne la liste des directions possibles
         */
        public static String ListeDirection()
        {
            String s = "";
            Console.WriteLine("taille : " + nomsSorties.Count());
            foreach (String nom in nomsSorties){
                s += nom  + " /";
            }
            return s;
        }
    }
}
